#include "include/VectorTest.h"
#include "include/App.h"

#include "include/NetworkInterface.h"
#include "include/NetworkMethods.h"

#include "include/Scripting.h"


using namespace Ei;
using namespace Ogre;
//////////////////////////////////////////////////////////////////////////////
// Network Events 
///////////////////////////////////////////////////////////////////////////////

NetworkEvents::NetworkEvents(){}
NetworkEvents::~NetworkEvents(){}

//
// Default functions
//

void NetworkEvents::getHexamiteData(const WOscMessage *message)
{
   eilog("got hexamiteData");	
}


void NetworkEvents::GetMagData(const WOscMessage *message)
{
if  (message->GetNumInts() >= 4)   
	{
	int dev,X,Y,Z;
	// invert X and Z to put Magdata in the same plane as Accdata
	// also swap Z and Y here 	
	dev = message->GetInt(0);
	X = message->GetInt(1) * -1;
	Z = message->GetInt(2) * -1; 
	Y = message->GetInt(3);
	
    	Vector3 raw(X,Y,Z);			  			
	App::magAcc()->insertMagData(raw);
	
	}
}

void NetworkEvents::GetAccData(
	const WOscMessage *message)
	//const WOscTimeTag& when,
	//const TheNetReturnAddress* networkReturnAddress)
{
if  (message->GetNumInts() >= 4)   
	{

	int dev,X,Y,Z;
	// swap Z and Y here 
	dev = message->GetInt(0);
	X = message->GetInt(1);
	Z = message->GetInt(2);
	Y = message->GetInt(3);
		
    	Vector3 raw(X,Y,Z); 
	 
     	App::magAcc()->insertAccData(raw);
	}

}



void NetworkEvents::setNodePosition(
	const WOscMessage *message)
//	const WOscTimeTag& when,
//	const TheNetReturnAddress* networkReturnAddress)
{	
	if(isValidMessage(message, 3))
	 { 
		Vector3 pos(message->GetFloat(0),
			    message->GetFloat(1),
			    message->GetFloat(2));
			    		
		//actually move the node
		App::sceneMgr()->getSceneNode(String(message->GetString(0).GetBuffer()))->setPosition(pos);			
	}
	eilog("done Postion");
}

void NetworkEvents::setNodeOrientation(
	const WOscMessage *message)
//	const WOscTimeTag& when,
//	const TheNetReturnAddress* networkReturnAddress)
{	
	if(isValidMessage(message, 4))
	 { 	     		
	
		Quaternion quat(message->GetFloat(0), 
			        message->GetFloat(1),
				message->GetFloat(2),
				message->GetFloat(3));
		
		//actually rotate the node
		App::sceneMgr()->getSceneNode(String(message->GetString(0).GetBuffer()))->setOrientation(quat);		
	}
	eilog("done Orientation");
}




/// private functions



bool NetworkEvents::isValidMessage(const WOscMessage *message, int varNum)
{
	
	if  (message->GetNumStrings() >= 1)   
	{		
	  if(App::sceneMgr()->hasSceneNode(String(message->GetString(0).GetBuffer())))
	  {
	       if (message->GetNumFloats() >= varNum)
	       {// A valid Message
		
		return true;			
	       }
	      else
	       {
		
	       eilog("Specifiy " + StringConverter::toString(varNum) + " Floats to process this message");
	       return false;
	       }			
	  }
	  else
	  {
		eilog(String(message->GetString(0).GetBuffer()) + " is not in the scene graph");
		return false;		
	  }	   	
	}
	else
	{
	eilog("Invalid setNodePosition message, you need to specify a string");	
	return false;
	}
return false;
}

//////////////////////////////////////////////////////////////////////////////
// Network Methods, 
///////////////////////////////////////////////////////////////////////////////

// Constructor. Sets the method name and info in the base class.            
NetworkMethod::NetworkMethod(
	WOscContainer* parent,
	NetworkInterface* receiverContext,
	char* adress,
	void (NetworkEvents::*EventUsed) (const WOscMessage *)//, const WOscTimeTag& , const TheNetReturnAddress*) //WOscMessage *, WOscTimeTag& , TheNetReturnAddress*)
	)
:NetworkBaseMethod(
	parent,
	receiverContext,
	adress,
	"Ei defined method.")
{
	mEvent = EventUsed;
	mDoOwnOSC = App::scripting()->getTableBool("net", "UseOwnOSC");	
}
  
void NetworkMethod::Method(
	const WOscMessage *message,
	const WOscTimeTag& when,
	const TheNetReturnAddress* networkReturnAddress)
{

//
// check if the OSC is my own, otherwise execute the function
//
	if (!(mDoOwnOSC)) 
	{	
		if (networkReturnAddress->m_addr.sin_addr.s_addr !=
	    	App::netMgr()->getLocalIP().s_addr)
		{	
		(mEvents.*mEvent)(message);//, when, networkReturnAddress);
		}
	}
	else
	{
	(mEvents.*mEvent)(message);//, when, networkReturnAddress);	
	}
}
